www.gusucode.com > 基于Visual C++高级界面特效制作百例源码程序 > 基于Visual C++高级界面特效制作百例源码程序/code/char17/pagewnd/PageWnd.cpp
// PageWnd.cpp : implementation file // #include "stdafx.h" #include "math.h" //#include "TestPage.h" #include "PageWnd.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CPageWnd CPageWnd::CPageWnd(int nrows, int ncols) { m_nrows = nrows; m_ncols = ncols; m_ncells = m_nrows * m_ncols; Init(); } CPageWnd::~CPageWnd() { if(m_pScrollData) delete m_pScrollData; if(m_pDefFont) delete m_pDefFont; if(m_pDefFontBold) delete m_pDefFontBold; delete m_pEditCtrl; if(m_pBrushList) { int nItems = m_pBrushList->GetSize(); for(int i = 0; i < nItems; i++) delete (*m_pBrushList)[i]; delete m_pBrushList; } if(m_pFontList) { int nItems = m_pFontList->GetSize(); for(int i = 0; i < nItems; i++) delete (*m_pFontList)[i]; delete m_pFontList; } if(m_pGridPen) delete m_pGridPen; for(int i = 0; i < m_ncells; i++) delete m_pCells[i]; delete []m_pCells; delete []m_height; delete []m_width; } BEGIN_MESSAGE_MAP(CPageWnd, CWnd) //{{AFX_MSG_MAP(CPageWnd) ON_WM_CREATE() ON_WM_PAINT() ON_WM_SIZE() ON_WM_HSCROLL() ON_WM_VSCROLL() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_SETCURSOR() ON_WM_KEYDOWN() ON_WM_CHAR() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPageWnd message handlers void CPageWnd::Init() { m_pEditCtrl = new CPageEdit(); BkgndColor = GetSysColor(COLOR_BTNFACE); m_height = new int[m_nrows]; m_width = new int[m_ncols]; m_pCells = new CCell*[m_ncells]; for(int i = 0; i < m_ncells; i++) m_pCells[i] = new CCell; m_pScrollData = 0; m_pDefFont = 0; m_pDefFontBold = 0; m_bCapture = false; //capturing is not in progress m_ex_x = - 1; //capturing prevoius x position m_bGrid = true; m_charClip = '.'; m_bReadOnly = false; m_CurSize = LoadCursor(NULL, IDC_SIZEWE); m_CurArrow = LoadCursor(NULL, IDC_ARROW); //ex position and current position of edit control m_rowEdit = 1; m_colEdit = 1; m_rowEditEx = 1; m_colEditEx = 1; m_EditRect.SetRectEmpty(); } int CPageWnd::HeightInPixels(int h) { CClientDC dc(this); return MulDiv(-h, dc.GetDeviceCaps(LOGPIXELSY), 72); } int CPageWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; CRect r(0, 0, 0, 0); m_pEditCtrl->Create(WS_CHILD | ES_LEFT | ES_WANTRETURN | WS_BORDER, r, this, 201); LOGFONT lf; TEXTMETRIC tm; ZeroMemory(&lf, sizeof(lf)); lf.lfWeight = FW_NORMAL; lf.lfHeight = HeightInPixels(8); lf.lfCharSet = DEFAULT_CHARSET; strcpy(lf.lfFaceName, "Verdana"); m_pDefFont = new CFont(); if(!m_pDefFont->CreateFontIndirect(&lf)) { HFONT stdFont = HFONT(::GetStockObject(ANSI_VAR_FONT)); ::GetObject(stdFont, sizeof(lf), &lf); m_pDefFont->CreateFontIndirect(&lf); } LOGFONT lf2 = lf; m_pDefFontBold = new CFont(); lf2.lfWeight = FW_BOLD; m_pDefFontBold->CreateFontIndirect(&lf2); CClientDC dc(this); dc.SelectObject(m_pDefFont); dc.GetTextMetrics(&tm); m_stdwidth = 5 * tm.tmMaxCharWidth; m_stdheight = (3 * tm.tmHeight) / 2; m_pScrollData = new CScrollData; m_pScrollData->XUnit = m_stdwidth; m_pScrollData->YUnit = m_stdheight; m_pScrollData->XRange = m_ncols - 2; m_pScrollData->YRange = m_nrows - 2; m_PageSize.cx = 0; m_PageSize.cy = 0; for(int row = 0; row < m_nrows; row++) { m_height[row] = m_stdheight; m_PageSize.cy += m_height[row]; } for(int col = 0; col < m_ncols; col++) { m_width[col] = m_stdwidth; m_PageSize.cx += m_width[col]; } m_pBrushList= new CArray<CBrush*, CBrush*>; m_pFontList = new CArray<CFont*, CFont*>; m_pBrushList->SetSize(0, 1); m_pBrushList->SetSize(0, 1); CFont* pDefFont = new CFont(); pDefFont->CreateFontIndirect(&lf); m_pFontList->Add(pDefFont); COLORREF c1 = GetSysColor(COLOR_BTNFACE); COLORREF c2 = GetSysColor(COLOR_WINDOW); m_pBrushList->Add(new CBrush(c1)); m_pBrushList->Add(new CBrush(c2)); for(row = 0; row < m_nrows; row++) { SetCellColor(row, 0, c1); SetCellAlign(row, 0, TA_CENTER); } for(col = 0; col < m_ncols; col++) { SetCellColor(0, col, c1); SetCellAlign(0, col, TA_CENTER); } for(row = 1; row < m_nrows; row++) for(col = 1; col < m_ncols; col++) SetCellColor(row, col, c2); m_pGridPen = new CPen(PS_SOLID, 1, c1); return 0; } // // Cell index functions // ~~~~~~~~~~~~~~~~~~~~ // // from cell index in structure (idx) to cell position in page (row, col) // void CPageWnd::GetCellPosition(int idx, int& row, int& col) { if(idx < 0 || idx >= m_ncells) { char szDebug[64]; sprintf(szDebug, "Cell index %d is not valid", idx); OutputDebugString(szDebug); row = -1; col = -1; } else { row = idx / m_ncols; col = int(fmod(idx, m_ncols)); } } // reverse // int CPageWnd::GetCellIndex(int row, int col) { if( (row < 0 || row >= m_nrows) || (col < 0 || col >= m_ncols) ) { char szDebug[64]; sprintf(szDebug, "Cell page idx (%d, %d) is not valid", row, col); OutputDebugString(szDebug); return -1; } else return (row * m_ncols + col); } // get pointer on cell at row, col position // CCell* CPageWnd::GetCell(int row, int col) { int cellIdx = GetCellIndex(row, col); if(cellIdx == -1) return 0; //null cell else return m_pCells[cellIdx]; } // get pointer with index cellIdx // CCell* CPageWnd::GetCell(int cellIdx) { if(cellIdx < 0 || cellIdx >= m_ncells) return 0; //null cell else return m_pCells[cellIdx]; } void CPageWnd::OnPaint() { CPaintDC dc(this); CRect& rect = *(CRect*)&dc.m_ps.rcPaint; Paint(dc, dc.m_ps.fErase, rect); } void CPageWnd::Paint(CDC& dc, BOOL erase, CRect& rect) { BOUND bound; //find start and end col nearest to invRect boundaries int width = m_width[0]; bound.startcol = m_pScrollData->XPos + 1; if(width < rect.left) { while(width < rect.left && bound.startcol < m_ncols) width += m_width[bound.startcol++]; bound.startcol -= 1; width -= m_width[bound.startcol]; } bound.startwidth = width; bound.endcol = bound.startcol; while(width < rect.right && bound.endcol < m_ncols) width += m_width[bound.endcol++]; bound.endwidth = width; //find start and end row nearest to invRect boundaries int height = m_height[0]; bound.startrow = m_pScrollData->YPos + 1; if(height < rect.top) { while(height < rect.top && bound.startrow < m_nrows) height += m_height[bound.startrow++]; bound.startrow -= 1; height -= m_height[bound.startrow]; } bound.startheight = height; bound.endrow = bound.startrow; while(height < rect.bottom && bound.endrow < m_nrows) height += m_height[bound.endrow++]; bound.endheight = height; Draw_ZeroZero(dc, rect); Draw_ZeroRow(dc, bound); Draw_ZeroCol(dc, bound); Draw_Contents(dc, bound); if(m_bGrid) Draw_Grid(dc, bound); if(!m_pEditCtrl->IsWindowVisible()) MarkActiveCell(false, true); //update empty area CBrush* pBkBrush = new CBrush(BkgndColor); if(bound.endwidth < rect.right) { CRect r(bound.endwidth, rect.top, rect.right, rect.bottom); dc.SelectObject(pBkBrush); dc.PatBlt(r.left, r.top, r.Width(), r.Height(), PATCOPY); } if(bound.endheight < rect.bottom) { CRect r(rect.left, bound.endheight, rect.right, rect.bottom); dc.SelectObject(pBkBrush); dc.PatBlt(r.left, r.top, r.Width(), r.Height(), PATCOPY); } delete pBkBrush; } //drawing cell text // void CPageWnd::CellEntry(CDC& dc, int row, int col, CRect cellRect) { char* celltext = GetCellTextPtr(row, col); if(celltext == 0) return; cellRect.InflateRect(-1, -1); if(dc.GetBkMode() != TRANSPARENT); dc.SetBkMode(TRANSPARENT); dc.SelectObject(GetCellFont(row, col)); bool useclip = false; CSize textsize = dc.GetTextExtent(celltext, strlen(celltext)); if(row > 0 && col > 0 && textsize.cx > cellRect.Width()) useclip = true; int x0, y0; y0 = cellRect.bottom - 2; short align = GetCellAlign(row, col); switch(align) { case TA_LEFT: x0 = cellRect.left + 2; break; case TA_CENTER: x0 = (cellRect.left + cellRect.right) / 2; break; case TA_RIGHT: x0 = cellRect.right - 2; break; } dc.SetTextAlign(align | TA_BOTTOM); dc.SetTextColor(GetCellTextColor(row, col)); if(useclip) { textsize = dc.GetTextExtent(&m_charClip, 1); int nchars = cellRect. Width() / textsize.cx + 2; char* lpszText = new char[nchars + 1]; int i = 0; while(i < nchars) lpszText[i++] = m_charClip; lpszText[i] = 0; dc.ExtTextOut(x0, y0, ETO_CLIPPED, &cellRect, lpszText, strlen(lpszText), 0); delete []lpszText; } else dc.ExtTextOut(x0, y0, ETO_CLIPPED, &cellRect, celltext, strlen(celltext), 0); } //drawing 0,0 cell // void CPageWnd::Draw_ZeroZero(CDC& dc, CRect& rect) { if(rect.left < m_width[0] || rect.top < m_height[0] || (m_bCapture /*&& m_idx == 0*/)) { CRect cellRect(0, 0, m_width[0] + 1, m_height[0] + 1); dc.DrawEdge(&cellRect, EDGE_ETCHED, BF_RECT | BF_MIDDLE); } } //zero row painting (invRect as invalidated rect) // void CPageWnd::Draw_ZeroRow(CDC& dc, BOUND& bound) { CRect cell(bound.startwidth, 0, bound.endwidth + 1, m_height[0]); for(int col = bound.startcol; col < bound.endcol; col++) { cell.right = cell.left + m_width[col]; CRect borRect(cell.left, cell.top, cell.right, cell.bottom); dc.DrawEdge(&borRect, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE); CellEntry(dc, 0, col, borRect); cell.left = cell.right; } } // //zero column painting // void CPageWnd::Draw_ZeroCol(CDC& dc, BOUND& bound) { CRect cell(0, bound.startheight, m_width[0], bound.endheight); for(int row = bound.startrow; row < bound.endrow; row++) { cell.bottom = cell.top + m_height[row]; CRect borRect(cell.left, cell.top, cell.right, cell.bottom); dc.DrawEdge(&borRect, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE); CellEntry(dc, row, 0, borRect); cell.top = cell.bottom; } } // //painting all cell contents except zero row and column // void CPageWnd::Draw_Contents(CDC& dc, BOUND& bound) { CRect cellRect(bound.startwidth, bound.startheight, bound.startwidth + m_width[bound.startcol], bound.startheight + m_height[bound.startrow]); for(int row = bound.startrow; row < bound.endrow; row++) { cellRect.left = bound.startwidth; for(int col = bound.startcol; col < bound.endcol; col++) { cellRect.right = cellRect.left + m_width[col]; dc.SelectObject(GetCellBrush(row, col)); dc.PatBlt(cellRect.left, cellRect.top, cellRect.Width(), cellRect.Height(), PATCOPY); CellEntry(dc, row, col, cellRect); cellRect.left = cellRect.right; } cellRect.top = cellRect.bottom; cellRect.bottom = cellRect.bottom + m_height[row]; } } // //grid drawing // void CPageWnd::Draw_Grid(CDC& dc, BOUND& bound) { dc.SelectObject(*m_pGridPen); CRect cellRect(bound.startwidth, bound.startheight, bound.startwidth + m_width[bound.startcol], bound.startheight + m_height[bound.startrow]); //vertical lines int y = bound.startheight; for(int row = bound.startrow; row < bound.endrow; row++) { dc.MoveTo(bound.startwidth, y); dc.LineTo(bound.endwidth, y); y += m_height[row]; } int x = bound.startwidth; for(int col = bound.startcol; col < bound.endcol; col++) { dc.MoveTo(x, bound.startheight); dc.LineTo(x, bound.endheight); x += m_width[col]; } } CBrush* CPageWnd::GetCellBrush(int row, int col) { CCell* cell = GetCell(row, col); if(cell) { CBrush* pbrush = (*m_pBrushList)[cell->m_bClrIdx]; if(pbrush) { return (pbrush); } } return 0; } //background color COLORREF CPageWnd::GetCellColor(int row, int col) { CCell* cell = GetCell(row, col); if(cell) { CBrush* pbrush = (*m_pBrushList)[cell->m_bClrIdx]; if(pbrush) { LOGBRUSH lb; pbrush->GetObject(sizeof(lb), &lb); return lb.lbColor; } } return (COLORREF(GetSysColor(COLOR_WINDOW))); } //returns brush index in list or -1 if not successful // int CPageWnd::SetCellColor(int row, int col, COLORREF clr) { CCell* cell = GetCell(row, col); if(cell) { CBrush *pbrush = new CBrush(clr); LOGBRUSH lb; pbrush->GetObject(sizeof(lb), &lb); //compare whole LOGBRUSH, not just color cell->m_bClrIdx = -1; int n = m_pBrushList->GetSize(); for(int i = 0; i < n; i++) { LOGBRUSH lbFound; (*m_pBrushList)[i]->GetObject(sizeof(lbFound), &lbFound); int comp = memcmp(&lb, &lbFound, sizeof(LOGBRUSH)); if(comp == 0) { cell->m_bClrIdx = i; delete pbrush; break; } } if(cell->m_bClrIdx == -1) //not found cell->m_bClrIdx = m_pBrushList->Add(pbrush); return cell->m_bClrIdx; } return -1; } BOOL CPageWnd::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Add your specialized code here and/or call the base class cs.style |= WS_HSCROLL | WS_VSCROLL; return CWnd::PreCreateWindow(cs); } void CPageWnd::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); if(nType != SIZE_MINIMIZED) { AdjustScrollBars(); Invalidate(false); } } void CPageWnd::AdjustScrollBars() { CRect r; GetClientRect(&r); SCROLLINFO si; int i; //horizontal scroll bar // //determine x page size int cx_visible = m_width[0]; i = m_pScrollData->XPos + 1; while(cx_visible < r.right && i < m_pScrollData->XRange) cx_visible += m_width[i++]; m_pScrollData->XPage = i - m_pScrollData->XPos; si.cbSize = sizeof(si); si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMin = 0; si.nMax = m_pScrollData->XRange; si.nPage = m_pScrollData->XPage; si.nPos = m_pScrollData->XPos; ::SetScrollInfo(m_hWnd, SB_HORZ, &si, true); //vertical scroll bar // //determine y page size int cy_visible = m_height[0]; i = m_pScrollData->YPos + 1; while(cy_visible < r.bottom && i < m_pScrollData->YRange) cy_visible += m_height[i++]; m_pScrollData->YPage = i - m_pScrollData->YPos; si.cbSize = sizeof(si); si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMin = 0; si.nMax = m_pScrollData->YRange; si.nPage = m_pScrollData->YPage; si.nPos = m_pScrollData->YPos; ::SetScrollInfo(m_hWnd, SB_VERT, &si, true); int sum; if(m_pScrollData->YPos != 0) ShowScrollBar(SB_VERT, true); //show vert scrollbar else { sum = 0; for(i = 0; i < m_nrows; i++) sum += m_height[i]; if(sum >= r.Height()) ShowScrollBar(SB_VERT, true); //show vert scrollbar else ShowScrollBar(SB_VERT, false); //hide vert scrollbar } if(m_pScrollData->XPos != 0) ShowScrollBar(SB_HORZ, true); //show vert scrollbar else { sum = 0; for(i = 0; i < m_ncols; i++) sum += m_width[i]; if(sum >= r.Width()) ShowScrollBar(SB_HORZ, true); else ShowScrollBar(SB_HORZ, false); //do not show horz scrollbar } } void CPageWnd::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { if(m_pEditCtrl->IsWindowVisible()) m_pEditCtrl->SendMessage(WM_CHAR, VK_RETURN, 0L); int inc = 0; switch(nSBCode) { case SB_LINEUP: inc = -1; break; case SB_LINEDOWN: inc = 1; break; case SB_PAGEUP: inc = -m_pScrollData->XPage; break; case SB_PAGEDOWN: inc = m_pScrollData->XPage; break; case SB_THUMBPOSITION: inc = nPos - m_pScrollData->XPos; break; } if(inc == 0) return; //determine amount of pixels to scroll int delta = 0; int col, newpos; if(inc > 0) { newpos = min(m_pScrollData->XRange, m_pScrollData->XPos + inc); col = m_pScrollData->XPos + 1; while(col <= newpos) //zero col (when XPos = 0) is not scrolled delta += m_width[col++]; } else { //inc < 0 newpos = max(0, m_pScrollData->XPos + inc); col = m_pScrollData->XPos; while(col > newpos) delta -= m_width[col--]; } m_pScrollData->XPos = newpos; CRect rcClient; GetClientRect(&rcClient); CRect scrollRect(m_width[0] + 1, 0, rcClient.right, rcClient.bottom); ScrollWindowEx(-delta, 0, &scrollRect, &scrollRect, 0, 0, SW_INVALIDATE | SW_SCROLLCHILDREN); SCROLLINFO si; si.cbSize = sizeof(si); si.fMask = SIF_POS; si.nPos = m_pScrollData->XPos; ::SetScrollInfo(m_hWnd, SB_HORZ, &si, true); m_EditRect.OffsetRect(/*m_EditRect.left + */delta, 0/*m_EditRect.top*/); UpdateWindow(); } void CPageWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { if(m_pEditCtrl->IsWindowVisible()) m_pEditCtrl->SendMessage(WM_CHAR, VK_RETURN, 0L); int inc = 0; switch(nSBCode) { case SB_LINEUP: inc = -1; break; case SB_LINEDOWN: inc = 1; break; case SB_PAGEUP: inc = -m_pScrollData->YPage; break; case SB_PAGEDOWN: inc = m_pScrollData->YPage; break; case SB_THUMBPOSITION: inc = nPos - m_pScrollData->YPos; break; } if(inc == 0) return; //determine amount of pixels to scroll int delta = 0; int row, newpos; if(inc > 0) { newpos = min(m_pScrollData->YRange, m_pScrollData->YPos + inc); row = m_pScrollData->YPos + 1; while(row <= newpos) //zero row ( YPos = 0) is not scrolled delta += m_height[row++]; } else { //inc < 0 newpos = max(0, m_pScrollData->YPos + inc); row = m_pScrollData->YPos; while(row > newpos) delta -= m_height[row--]; } m_pScrollData->YPos = newpos; CRect rcClient; GetClientRect(rcClient); CRect scrollRect(0, m_height[0] + 1, rcClient.right, rcClient.bottom); ScrollWindowEx(0, -delta, &scrollRect, &scrollRect, 0, 0, SW_INVALIDATE | SW_SCROLLCHILDREN); SCROLLINFO si; si.cbSize = sizeof(si); si.fMask = SIF_POS; si.nPos = m_pScrollData->YPos; ::SetScrollInfo(m_hWnd, SB_VERT, &si, true); m_EditRect.OffsetRect(0/*m_EditRect.left*/, /*m_EditRect.top + */delta); UpdateWindow(); } //cell text functions //~~~~~~~~~~~~~~~~~~~ // returns cell text pointer (useful in internal loops) // char* CPageWnd::GetCellTextPtr(int row, int col) { CCell* cell = GetCell(row, col); if(cell) return cell->m_pcontents; else return 0; } // reverse // bool CPageWnd::SetCellText(int row, int col, char* szText) { CCell* cell = GetCell(row, col); if(cell) { if(cell->m_pcontents) delete []cell->m_pcontents; int n = strlen(szText); cell->m_pcontents = new char[n + 1]; strncpy(cell->m_pcontents, szText, n + 1); return true; } return false; } // copies cell text in szText (for public use). Copies up to cb chars // int CPageWnd::GetCellText(int row, int col, char* szText, int cb) { CCell* cell = GetCell(row, col); if(cell) { if(cell->m_pcontents) { strncpy(szText, cell->m_pcontents, cb); return strlen(szText); } } return 0; } //cell font functions //~~~~~~~~~~~~~~~~~~~~ HFONT CPageWnd::GetCellFontHandle(int row, int col) { CCell* cell = GetCell(row, col); if(cell) { CFont* pfont = (*m_pFontList)[cell->m_fontIdx]; if(pfont) { return (HFONT(*pfont)); } } return 0; } CFont* CPageWnd::GetCellFont(int row, int col) { CCell* cell = GetCell(row, col); if(cell) { CFont* pfont = (*m_pFontList)[cell->m_fontIdx]; if(pfont) return (pfont); } return 0; } // set cell font using LOGFONT // int CPageWnd::SetCellFont(int row, int col, LOGFONT* plf) { CCell* cell = GetCell(row, col); if(cell) { cell->m_fontIdx = -1; int n = m_pFontList->GetSize(); for(int i = 0; i < n; i++) { LOGFONT lfFound; (*m_pFontList)[i]->GetObject(sizeof(lfFound), &lfFound); int comp = memcmp(plf, &lfFound, sizeof(LOGFONT)); if(comp == 0) { cell->m_fontIdx = i; break; } } if(cell->m_fontIdx == -1) { //not found CFont* pFont = new CFont; pFont->CreateFontIndirect(plf); cell->m_fontIdx = m_pFontList->Add(pFont); } return cell->m_fontIdx; } return -1; } // set cell font using HFONT // int CPageWnd::SetCellFont(int row, int col, HFONT hfont) { CCell* cell = GetCell(row, col); if(cell) { CFont *pfont = new CFont(); LOGFONT lf; GetObject(hfont, sizeof(lf), &lf); pfont->CreateFontIndirect(&lf); cell->m_fontIdx = -1; int n = m_pFontList->GetSize(); for(int i = 0; i < n; i++) { LOGFONT lfFound; (*m_pFontList)[i]->GetObject(sizeof(lfFound), &lfFound); int comp = memcmp(&lf, &lfFound, sizeof(LOGFONT)); if(comp == 0) { cell->m_fontIdx = i; delete pfont; break; } } if(cell->m_fontIdx == -1) //not found cell->m_fontIdx = m_pFontList->Add(pfont); return cell->m_fontIdx; } return -1; } // use existing font to set cell font // int CPageWnd::SetCellFont(int row, int col, int index) { CCell* cell = GetCell(row, col); if(cell) { int maxidx = m_pFontList->GetSize() - 1; if(index <= maxidx) cell->m_fontIdx = index; return cell->m_fontIdx; } return -1; } //cell alignment functions //~~~~~~~~~~~~~~~~~~~~~~~~ void CPageWnd::SetCellAlign(int row, int col, short fAlign) { CCell* cell = GetCell(row, col); if(cell) cell->m_falign = fAlign; } short CPageWnd::GetCellAlign(int row, int col) { CCell* cell = GetCell(row, col); if(cell) return cell->m_falign; else return 0; } //text color //~~~~~~~~~~ COLORREF CPageWnd::GetCellTextColor(int row, int col) { CCell* cell = GetCell(row, col); if(cell) return cell->m_fclr; else return (COLORREF(::GetSysColor(COLOR_WINDOWTEXT))); } void CPageWnd::SetCellTextColor(int row, int col, COLORREF clr) { CCell* cell = GetCell(row, col); if(cell) cell->m_fclr = clr; } void CPageWnd::OnLButtonDown(UINT nFlags, CPoint point) { if(m_pEditCtrl->IsWindowVisible()) m_pEditCtrl->SendMessage(WM_CHAR, VK_RETURN, 0L); SetFocus(); CRect r; int i, j; //is in active zone? (active cell marker) // if(point.x > m_width[0] && point.y > m_height[0]) { int x_sum = m_width[0]; i = m_pScrollData->XPos + 1; while(x_sum < point.x) { x_sum += m_width[i++]; if(i > m_ncols) return; } int y_sum = m_height[0]; j = m_pScrollData->YPos + 1; while(y_sum < point.y) { y_sum += m_height[j++]; if(j > m_nrows) return; } m_rowEditEx = m_rowEdit; m_colEditEx = m_colEdit; m_colEdit = i - 1; m_rowEdit = j - 1; MarkActiveCell(true, true); return; } //is in split column line? // m_idx = IsSplitLine(point.x, point.y); if(m_idx >= 0 && m_width[m_idx] == 0) return; if(m_idx >= 0) { if(m_idx == 0) m_left_limit = 0; else m_left_limit = m_width[0]; for(i = m_pScrollData->XPos + 1; i < m_idx; i++) { m_left_limit += m_width[i]; if(i > m_ncols) return; } GetClientRect(&r); m_right_limit = r.right; SetCapture(); m_bCapture = true; m_ex_x = -1; } CWnd::OnLButtonDown(nFlags, point); } void CPageWnd::OnLButtonUp(UINT nFlags, CPoint point) { if(m_bCapture) { m_width[m_idx] = max((point.x - m_left_limit), 25); m_width[m_idx] = max((point.x - m_left_limit), 25); CRect rcClient; GetClientRect(&rcClient); rcClient.left = point.x - m_width[m_idx]; InvalidateRect(rcClient, false); UpdateWindow(); m_bCapture = false; ReleaseCapture(); m_idx = -1; AdjustScrollBars(); } CWnd::OnLButtonUp(nFlags, point); } void CPageWnd::OnMouseMove(UINT nFlags, CPoint point) { CRect r; //static bool prev_state = false; GetClientRect(r); if(m_bCapture) { if(! ( (point.x - m_left_limit) < 25 || (point.x > m_right_limit) ) ) { m_width[m_idx] = max((point.x - m_left_limit), 25); CRect rcClient; GetClientRect(&rcClient); rcClient.left = point.x - m_width[m_idx]; InvalidateRect(rcClient, false); UpdateWindow(); m_ex_x = point.x; } } /*else { //tooltip staff int x_sum = m_width[0]; int col = m_pScrollData->XPos + 1; while(x_sum < point.x && col < m_ncols) { x_sum += m_width[col++]; } col -= 1; if(col > 0 && col != m_ToolTipCol) { TRect r; r.left = x_sum - m_width[col - 1]; r.right = x_sum; r.top = 0; r.bottom = m_height[0]; m_pToolInfo->SetRect(r); m_ToolTipCol = col; m_pToolTip->NewToolRect(*m_pToolInfo); } }*/ CWnd::OnMouseMove(nFlags, point); } // // return column for resizing or -1 if x, y is not over cell border // int CPageWnd::IsSplitLine(int x, int y) { int sum, i; if(y > m_height[0] || x < 3) return -1; sum = m_width[0]; i = max(1, m_pScrollData->XPos + 1); while(sum < x && i < m_ncols) sum += m_width[i++]; i -= 1; if(abs(sum - x) < 2) return i; else sum -= m_width[i]; if((x - sum) < 2) return (i - 1); return -1; } BOOL CPageWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if(nHitTest == HTCLIENT && message) { POINT pt; GetCursorPos(&pt); ScreenToClient(&pt); if( IsSplitLine(pt.x, pt.y) >= 0 || m_bCapture ) ::SetCursor(m_CurSize); else ::SetCursor(m_CurArrow); } else ::SetCursor(m_CurArrow); return true; } void CPageWnd::MarkActiveCell(bool fprev, bool fnext) { if(m_pEditCtrl->IsWindowVisible()) m_pEditCtrl->SendMessage(WM_CHAR, VK_RETURN, 0L); int i, xpos, ypos; CRect r(0, 0, 0, 0); CClientDC dc(this); dc.SelectStockObject(NULL_BRUSH); //ex active cell // if(fprev) { if(m_pScrollData->XPos < m_colEditEx && m_pScrollData->YPos < m_rowEditEx) { CPen inactivePen(PS_SOLID, 2, GetCellColor(m_rowEditEx, m_colEditEx)); dc.SelectObject(&inactivePen); CRect r(m_EditRect.left + 2, m_EditRect.top + 2, m_EditRect.right, m_EditRect.bottom); dc.Rectangle(r); MarkHeader(false); } } //active cell // if(fnext) { if(m_pScrollData->XPos < m_colEdit && m_pScrollData->YPos < m_rowEdit) { xpos = m_width[0]; for(i = m_pScrollData->XPos+ 1; i < m_colEdit; i++) xpos += m_width[i]; ypos = 0; for(i = 0; i < (m_rowEdit - m_pScrollData->YPos); i++) ypos += m_height[i]; m_EditRect.SetRect(xpos, ypos, xpos + m_width[m_colEdit], ypos + m_height[m_rowEdit]); CPen activePen(PS_SOLID, 2, ::GetSysColor(COLOR_WINDOWTEXT)); dc.SelectObject(&activePen); CRect r(m_EditRect.left + 2, m_EditRect.top + 2, m_EditRect.right, m_EditRect.bottom); dc.Rectangle(r); m_pEditCtrl->MoveWindow(r.left, r.top, r.Width(), r.Height(), false); MarkHeader(true); } } } void CPageWnd::MarkHeader(bool mark) { CRect rowRect(0, m_EditRect.top, m_width[0], m_EditRect.bottom); CRect colRect(m_EditRect.left, 0, m_EditRect.right, m_height[0]); CClientDC dc(this); if(!mark) { dc.DrawEdge(rowRect, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE); SetCellFont(m_rowEditEx, 0, *m_pDefFont); CellEntry(dc, m_rowEditEx, 0, rowRect); dc.DrawEdge(colRect, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE); SetCellFont(0, m_colEditEx, *m_pDefFont); CellEntry(dc, 0, m_colEditEx, colRect); } else { dc.DrawEdge(rowRect, BDR_RAISED, BF_RECT | BF_MIDDLE); SetCellFont(m_rowEdit, 0, *m_pDefFontBold); CellEntry(dc, m_rowEdit, 0, rowRect); dc.DrawEdge(colRect, BDR_RAISED, BF_RECT | BF_MIDDLE); SetCellFont(0, m_colEdit, *m_pDefFontBold); CellEntry(dc, 0, m_colEdit, colRect); } } void CPageWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { bool fPrev = true; CRect rClient; int i, sum; switch(nChar) { case VK_F2: { if(!m_bReadOnly) { m_pEditCtrl->SetFont(GetCellFont(m_rowEdit, m_colEdit), true); m_pEditCtrl->SetWindowText(GetCellTextPtr(m_rowEdit, m_colEdit)); m_pEditCtrl->ShowWindow(SW_SHOW); } break; } case VK_LEFT: { if(m_pScrollData->XPos && (m_pScrollData->XPos >= m_colEdit - 2) && m_colEdit > 1) SendMessage(WM_HSCROLL, SB_LINEUP, 0); if(m_colEdit - 1) { m_colEditEx = m_colEdit; m_rowEditEx = m_rowEdit; m_colEdit -= 1; MarkActiveCell(fPrev, true); } break; } case VK_RIGHT: { if(m_colEdit + 1 >= m_ncols) { SendMessage(WM_HSCROLL, SB_LINEDOWN, 0); return; } GetClientRect(&rClient); i = m_pScrollData->XPos + 1; sum = m_width[0]; while(i < m_colEdit + 2) sum += m_width[i++]; if(sum > rClient.right) SendMessage(WM_HSCROLL, SB_LINEDOWN, 0); m_colEditEx = m_colEdit; m_rowEditEx = m_rowEdit; m_colEdit += 1; MarkActiveCell(fPrev, true); break; } case VK_UP: { if( m_pScrollData->YPos && (m_rowEdit > 1) && (m_rowEdit - m_pScrollData->YPos) < 3 ) SendMessage(WM_VSCROLL, SB_LINEUP, 0); if(m_rowEdit - 1) { m_colEditEx = m_colEdit; m_rowEditEx = m_rowEdit; m_rowEdit -= 1; MarkActiveCell(fPrev, true); } break; } case VK_DOWN: { if(m_rowEdit + 1 >= m_nrows) { SendMessage(WM_VSCROLL, SB_LINEDOWN, 0); return; } GetClientRect(&rClient); //use height[1] becouse all rows have a same height (except 0. row) // if(m_rowEdit - m_pScrollData->YPos > rClient.bottom / m_height[1] - 2) SendMessage(WM_VSCROLL, SB_LINEDOWN, 0); m_colEditEx = m_colEdit; m_rowEditEx = m_rowEdit; m_rowEdit += 1; MarkActiveCell(fPrev, true); break; } } CWnd::OnKeyDown(nChar, nRepCnt, nFlags); } void CPageWnd::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { if(m_bReadOnly) return; if(isalnum(nChar) || nChar == '.') { m_pEditCtrl->SendMessage(WM_CHAR, WPARAM(nChar), MAKELPARAM(nRepCnt, nFlags)); } m_pEditCtrl->SetFont(GetCellFont(m_rowEdit, m_colEdit), true); m_pEditCtrl->ShowWindow(SW_SHOW); CWnd::OnChar(nChar, nRepCnt, nFlags); } // // change cell contents if accept = true // void CPageWnd::EditAccept(bool accept) { m_pEditCtrl->ShowWindow(SW_HIDE); if(accept) { char string[255]; m_pEditCtrl->GetWindowText(string, 255); SetCellText(m_rowEdit, m_colEdit, string); } m_pEditCtrl->SetWindowText(""); InvalidateRect(m_EditRect, false); } ///////////////////////////////////////////////////////////////////////////// // CPageEdit CPageEdit::CPageEdit() { m_pPage = 0; } CPageEdit::~CPageEdit() { } BEGIN_MESSAGE_MAP(CPageEdit, CEdit) //{{AFX_MSG_MAP(CPageEdit) ON_WM_CHAR() ON_WM_SHOWWINDOW() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPageEdit message handlers void CPageEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { if(!(nChar == VK_RETURN || nChar == VK_ESCAPE)) CEdit::OnChar(nChar, nRepCnt, nFlags); switch(nChar) { case VK_RETURN: if(m_pPage == 0) m_pPage = dynamic_cast<CPageWnd*>(GetParent()); if(m_pPage) m_pPage->EditAccept(true); break; case VK_ESCAPE: if(m_pPage == 0) m_pPage = dynamic_cast<CPageWnd*>(GetParent()); if(m_pPage) m_pPage->EditAccept(false); break; default: char szText[255]; GetWindowText(szText, 255); int n = strlen(szText); CSize size; CClientDC dc(this); dc.SelectObject(GetFont()); size = dc.GetTextExtent(szText, n); if(n) m_charWidth = size.cx / n; size.cx += 2 * m_charWidth; GetClientRect(&m_rcClient); if(m_rcClient.Width() <= size.cx) { m_rcClient.right += 2 * m_charWidth; SetWindowPos(0, m_rcClient.left, m_rcClient.top, m_rcClient.Width(), m_rcClient.Height(), SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW); } break; } } void CPageEdit::OnShowWindow(BOOL bShow, UINT nStatus) { CEdit::OnShowWindow(bShow, nStatus); if(bShow) { GetClientRect(&m_rcClient); SetFocus(); } }